package com.hzw.saas.service.rss.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.rss.*;
import com.hzw.saas.api.rss.bo.*;
import com.hzw.saas.common.config.util.PageParam;
import com.hzw.saas.common.config.util.PageUtils;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.common.util.SnowFlakeUtil;
import com.hzw.saas.service.rss.mapper.JournalCustomMapper;
import com.hzw.saas.service.rss.model.JournalCustom;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 期刊站点 服务实现类
 * </p>
 *
 * @author sonam
 * @since 2021-06-30
 */
@RequiredArgsConstructor
@Service("journalCustomService")
public class JournalCustomServiceImpl extends ServiceImpl<JournalCustomMapper, JournalCustom> implements IJournalCustomService, IService<JournalCustom> {
    @Autowired
    private JournalCustomMapper journalCustomMapper;

    @Resource(name = "journalService")
    private IJournalService journalService;

    @Resource(name = "journalCatalogUserService")
    private IJournalCatalogUserService journalCatalogUserService;

    @Resource(name = "journalUserActionService")
    private IJournalUserActionService journalUserActionService;

    @Resource(name = "journalUserAxisService")
    private IJournalUserAxisService journalUserAxisService;





    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addJournalCustom(List<JournalBO> journalBOS) {
        String pid = SnowFlakeUtil.nextIdStr();
        if (CollectionUtil.isNotEmpty(journalBOS)) {
            List<JournalBO> remoteJournals = journalService.findRepeatUrl(journalBOS);
            ArrayList<JournalCustom> journalCustoms = new ArrayList<>();
            ArrayList<JournalBO> alreadySave = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(remoteJournals)){
                journalBOS.forEach(journalBO -> {
                    remoteJournals.forEach(remoteJournal -> {
                        if (journalBO.getRssUrl().equals(remoteJournal.getRssUrl())){
                            JournalCustom map = MapperUtil.nf().map(journalBO, JournalCustom.class);
                            map.setJournalId(remoteJournal.getPid());
                            map.setPid(pid);
                            journalCustoms.add(map);
                            alreadySave.add(journalBO);
                        }
                    });
                });
            }
            if (CollectionUtil.isNotEmpty(journalCustoms)){
                this.saveBatch(journalCustoms);
                journalBOS.removeAll(alreadySave);
            }
            //剩下都是不重复的
            if(CollectionUtil.isNotEmpty(journalBOS)){
                journalBOS.forEach(journalBO -> {
                    journalBO.setPid(SnowFlakeUtil.nextIdStr());
                });
                List<JournalCustom> journalCustomList = MapperUtil.nf().mapAsList(journalBOS, JournalCustom.class);
                journalCustomList.forEach(journalCustom -> {
                    journalCustom.setJournalId(journalCustom.getPid());
                    journalCustom.setPid(pid);
                    journalCustom.setReadTime(new Date());
                });
                journalService.saveBatch(journalBOS);
                this.saveBatch(journalCustomList);
            }
        }
            return pid;
    }

    @Override
    public Page<JournalCustom> findCustomPage(PageParam pageParam, List<String> pids){
        if(CollectionUtil.isNotEmpty(pids)){
            Page<JournalCustom> page = this.page(pageParam.convert(), Wrappers.<JournalCustom>lambdaQuery().in(JournalCustom::getPid, pids)
                .eq(JournalCustom::getIsDelete, 0).orderByDesc(JournalCustom::getCreateTime));
            return page;
        }
        return new Page<>();
    }

    @Override
    public void moveCustom(String pid, String newCatalogId){
        JournalCatalogUserBO byId1 = journalCatalogUserService.findById(newCatalogId);
        if (byId1 == null){
            return;
        }
        if (byId1.getParentId().equals("0")||byId1.getParentId() == null){
            throw new RuntimeException("只能移动到二级目录下");
        }
        JournalCustom byId = this.getById(pid);
        if (byId != null){
            byId.setCatalogId(newCatalogId);
            updateById(byId);
        }
    }

    @Override
    public void updateJournalCustom(JournalBO journalBO) {
        //传入的是关联表主键
        String pid = journalBO.getPid();
        List<JournalCustom> list = this.lambdaQuery().eq(JournalCustom::getPid, pid).list();
        if (CollectionUtil.isNotEmpty(list)){
            JournalCustom journalCustom = list.get(0);
            String catalogId = journalCustom.getCatalogId();
            String journalId = journalCustom.getJournalId();
            MapperUtil.nf().map(journalBO,journalCustom);
            journalCustom.setJournalId(journalId);
            journalCustom.setCatalogId(catalogId);
            this.updateById(journalCustom);
        }
    }

    @Override
    public void deleteJournalCustomByCatalogId(List<String> catalogIds) {
        if (CollectionUtil.isNotEmpty(catalogIds)){
            journalCustomMapper.deleteByCatalogIds(catalogIds);
        }
    }

    @Override
    public List<JournalBO> findJournalCustom(String catalogId, String userId) {
        List<JournalCustom> list = this.lambdaQuery().eq(JournalCustom::getCatalogId, catalogId).list();
        //没有数据尝试刷新数据
        if (CollectionUtil.isEmpty(list)) {
            initializationCustom(userId,catalogId);
        }
        List<String> collect = list.stream().map(JournalCustom::getJournalId).collect(Collectors.toList());
        List<JournalBO> byIds = journalService.findByIds(collect);
        return byIds;
    }

    @Override
    public boolean findCountLeZero(String rssId){
        Integer count = this.lambdaQuery().eq(JournalCustom::getPid, rssId).count();
        if (count == 0){
            return true;
        }
        return  false;
    }

    private List<JournalBO> initializationCustom(String userId,String pid) {
        JournalCatalogUserBO one = journalCatalogUserService.findById(pid);
        String catalogId = one.getCatalogId();
        ArrayList<String> strings = new ArrayList<>();
        strings.add(catalogId);
        List<JournalBO> catalogByIds = journalService.findCatalogByIds(strings);
        if (CollectionUtil.isNotEmpty(catalogByIds)){
            List<JournalCustom> journalCustoms = MapperUtil.nf().mapAsList(catalogByIds, JournalCustom.class);
            journalCustoms.forEach(journalCustom -> {
                journalCustom.setJournalId(journalCustom.getPid());
                journalCustom.setCatalogId(pid);
                journalCustom.setPid(SnowFlakeUtil.nextIdStr());
            });
            this.saveBatch(journalCustoms);
            return MapperUtil.nt().mapAsList(journalCustoms,JournalBO.class);
        }

        return Collections.emptyList();
    }

    @Override
    public IPage<JournalBO> pageByCatalogIds(PageParam pageParam, List<String> catalogIds,String userId) {
        if(pageParam == null) {
            pageParam = new PageParam();
        }
        Page<JournalCustom> page = this.page(pageParam.convert(), Wrappers.<JournalCustom>lambdaQuery()
            .in(CollectionUtil.isNotEmpty(catalogIds), JournalCustom::getCatalogId, catalogIds));
        IPage<JournalBO> convert = PageUtils.convert(page, JournalBO.class);
        List<JournalBO> records = convert.getRecords();
        if (CollectionUtil.isEmpty(records)){
                List<JournalCatalogUserBO> journalCatalogUser = journalCatalogUserService.findJournalCatalogUser(userId);
                if (CollectionUtil.isEmpty(journalCatalogUser)){
                    return new Page<>();
                }
            ArrayList<String> strings = new ArrayList<>(journalCatalogUser.stream().map(JournalCatalogUserBO::getPid).collect(Collectors.toList()));
            List<JournalCustomBO> byCatalogIds = findByCatalogIds(strings);
            if (CollectionUtil.isEmpty(byCatalogIds)){
                strings.forEach(s -> {
                    initializationCustom(userId, s);
                });
            }
            page = this.page(pageParam.convert(), Wrappers.<JournalCustom>lambdaQuery()
                .in(JournalCustom::getCatalogId, catalogIds));
            convert = PageUtils.convert(page, JournalBO.class);
            records = convert.getRecords();
        }
        if (CollectionUtil.isNotEmpty(records)){
            List<JournalCustomBO> journalCustomBOS = MapperUtil.nf().mapAsList(records, JournalCustomBO.class);
            List<String> collect = journalCustomBOS.stream().map(JournalCustomBO::getJournalId).collect(Collectors.toList());
            List<JournalBO> byCatalogIds = journalService.findByIds(collect);
            if (CollectionUtil.isNotEmpty(byCatalogIds)){
                records.forEach(journalBO -> {
                    byCatalogIds.forEach(journalBO1 -> {
                        if (journalBO.getCatalogId().equals(journalBO1.getCatalogId())){
                            MapperUtil.nf().map(journalBO1,journalBO);
                        }
                    });
                });
            }
            List<String> collect1 = records.stream().map(JournalBO::getPid).collect(Collectors.toList());
            List<JournalCustom> list = this.lambdaQuery().in(JournalCustom::getPid, collect1).list();
            if (CollectionUtil.isNotEmpty(list)){
                List<String> collect2 = list.stream().map(JournalCustom::getJournalId).collect(Collectors.toList());
                List<JournalBO> byIds = journalService.findByIds(collect2);
                if (CollectionUtil.isNotEmpty(byIds)){
                    HashMap<String, JournalBO> stringStringHashMap = new HashMap<>();
                    records.forEach(journalBO -> {
                        list.forEach(journalCustom -> {
                            if (journalBO.getPid().equals(journalCustom.getPid())){
                                stringStringHashMap.put(journalCustom.getJournalId(),journalBO);
                            }
                        });
                    });
                    List<String> collect3 = byIds.stream().map(JournalBO::getPid).collect(Collectors.toList());
                    List<JournalCustomBO> journalCustomBOS1 = MapperUtil.nf().mapAsList(byIds, JournalCustomBO.class);
                    List<JournalUserAxisBO> unRead1 = journalUserAxisService.findUnRead(userId, collect3);
                    Map<String, Integer> unRead = journalUserActionService.findUnRead(journalCustomBOS1, userId,unRead1);
                    byIds.forEach(journalBO -> {
                        unRead.forEach((s3,i)->{
                            if (journalBO.getPid().equals(s3)){
                                journalBO.setUnReadNum(unRead.get(s3));
                            }
                        });
                      stringStringHashMap.forEach((s,s1)->{
                          if (journalBO.getPid().equals(s)){
                              String pid = s1.getPid();
                              s1.setJournalType(journalBO.getJournalType());
                              s1.setPid(pid);
                          }
                      });
                  });
                }
            }
        }
      return convert;

    }

    @Override
    public List<JournalCustomBO> findByCatalogIds(List<String> catalogIds) {
        if(CollectionUtil.isNotEmpty(catalogIds)){
            List<JournalCustom> list = this.lambdaQuery().in(JournalCustom::getCatalogId, catalogIds)
                .list();
            return MapperUtil.nt().mapAsList(list,JournalCustomBO.class);
        }
        return Collections.emptyList();
    }


    @Override
    public void deleteById(String pid) {
        if (StrUtil.isNotBlank(pid)){
            journalCustomMapper.deleteByPid(pid);
        }
    }

    @Override
    public List<JournalBO> findByPIds(List<String> collect) {
        if(CollectionUtil.isNotEmpty(collect)){
            List<JournalCustom> list = this.lambdaQuery().in(JournalCustom::getPid, collect).list();
            if (CollectionUtil.isEmpty(list)){
                List<String> collect1 = list.stream().map(JournalCustom::getJournalId).collect(Collectors.toList());
                List<JournalBO> byCatalogIds = journalService.findByCatalogIds(collect1);
                return byCatalogIds;
            }
            ArrayList<JournalBO> journalBOS = new ArrayList<>();
            list.forEach(journalCustom -> {
                JournalBO journalBO = new JournalBO();
                journalBO.setPid(journalCustom.getJournalId());
                journalBO.setCatalogId(journalCustom.getCatalogId());
                journalBO.setJournalName(journalCustom.getJournalName());
                journalBOS.add(journalBO);
            });
            return journalBOS;

        }

        return null;
    }

    @Override
    public JournalCustomBO findById(String pid) {
        JournalCustom byId = this.getById(pid);
        return MapperUtil.nf().map(byId,JournalCustomBO.class);
    }

    @Override
    public List<JournalCustomBO> findByIds(List<String> pids) {
        if (CollectionUtil.isNotEmpty(pids)){
            List<JournalCustom> list = this.lambdaQuery().in(JournalCustom::getPid, pids).list();
            return MapperUtil.nt().mapAsList(list,JournalCustomBO.class);
        }
        return null;
    }

    @Override
    public  List<JournalCustomBO> findByUserAndRssId(String userId, List<String> rssIds) {
        List<JournalCatalogUserBO> journalCatalogUserBOS = journalCatalogUserService.finByUser(userId);
        if (CollectionUtil.isNotEmpty(journalCatalogUserBOS)){
            List<String> collect = journalCatalogUserBOS.stream().map(JournalCatalogUserBO::getPid).collect(Collectors.toList());
            //防止数据不稳定遍历查询
            ArrayList<JournalCustom> journalCatalogUserBOS1 = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(rssIds)){
                rssIds.forEach(s -> {
                    List<JournalCustom> list = this.lambdaQuery().in(JournalCustom::getJournalId, s)
                        .in(JournalCustom::getCatalogId, collect)
                        .list();
                    if (CollectionUtil.isNotEmpty(list)){
                        journalCatalogUserBOS1.addAll(list);
                    }
                });

            }
            return MapperUtil.nt().mapAsList(journalCatalogUserBOS1,JournalCustomBO.class);


        }
        return null;
    }

    @Override
    public List<String> findAllByUser(String userId) {
        if (StrUtil.isBlank(userId)){
            return Collections.emptyList();
        }
        List<JournalCatalogUserBO> journalCatalogUser = journalCatalogUserService.findJournalCatalogUser(userId);
        if (CollectionUtil.isEmpty(journalCatalogUser)){
            return Collections.emptyList();
        }
        return journalCatalogUser.stream().map(JournalCatalogUserBO::getCatalogId).collect(Collectors.toList());
    }

    @Override
    public List<String> findAllJournalByUser(String userId) {
        List<String> allByUser = findAllByUser(userId);
        if (CollectionUtil.isEmpty(allByUser)){
            return Collections.emptyList();
        }
        List<JournalBO> byCatalogIds = journalService.findByCatalogIds(allByUser);
        if (CollectionUtil.isEmpty(byCatalogIds)){
            return Collections.emptyList();
        }
        return  byCatalogIds.stream().map(JournalBO::getPid).collect(Collectors.toList());
    }

    @Override
    public void updateBatch(List<JournalCustomBO> byUserAndRssId) {
        if (CollectionUtil.isNotEmpty(byUserAndRssId)){
            List<JournalCustom> journalCustomList = MapperUtil.nf().mapAsList(byUserAndRssId, JournalCustom.class);
            this.updateBatchById(journalCustomList);
        }
    }


}
